/* eslint-disable no-shadow */
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import createBrowserHistory from 'history/createBrowserHistory'
import { ConnectedRouter } from 'react-router-redux'

import configStore from './configStore'
import { createReducer } from './reducers'
import Root from './root'

let browserHistory = createBrowserHistory() // eslint-disable-line import/no-mutable-exports

export default function createApp() {
  let initReducers = {}
  let store = null
  let currentView = null
  let currentReducer = null
  let currentMiddlewares = [] // Create a browser history by default

  function view(view) {
    currentView = view

    return this
  }

  function reducer(reducers = {}) {
    // If passed with {"reducer1": reducer1, "reducer2": reducer2, ...}
    // Then combine the `system` reducer
    if (typeof reducers === 'object') {
      currentReducer = createReducer(reducers)
      initReducers = reducers
    } else {
      currentReducer = reducers
    }

    return this
  }

  function middleware(middlewares) {
    currentMiddlewares = middlewares

    return this
  }

  function render(container, callback) {
    ReactDOM.render(
      <Provider store={store}>
        <Root view={currentView} store={store} />
      </Provider>,
      container,
      callback,
    )
  }

  function run(container, callback) {
    if (typeof container === 'string') {
      container = document.querySelector(container) // eslint-disable-line  no-param-reassign
    }

    if (!currentReducer) {
      this.reducer()
    }

    store = configStore(currentReducer, browserHistory, currentMiddlewares)
    store.asyncReducers = initReducers

    render(container, callback)

    return this
  }

  function createHistory(options) {
    browserHistory = createBrowserHistory(options)

    return this
  }

  function getStore() {
    return store
  }

  return {
    view,
    reducer,
    middleware,
    run,
    createHistory,
    getStore,
  }
}

export { browserHistory, ConnectedRouter }
export asyncComponent from './components/asyncComponent'
